#include <openssl/evp.h>
#include <openssl/hmac.h>

#include <apr.h>
#include <apr_pools.h>
#include <apr_base64.h>
#include <apr_strings.h>

#include "aprs3.h"

char* s3_generate_signature(s3_request_t *req, 
                            serf_bucket_t *hdrs_bkt,
                            apr_pool_t *pool)
{
    char *signature = NULL;
    char  md[20];
    char *base64;
    const char *s3key = req->acceptor_baton->ctx->s3_key;
    const char *value;
    apr_uint32_t count;
    apr_uint32_t enclen;
    HMAC_CTX      hmac;

    /* Setup HMAC Context */
    HMAC_CTX_init(&hmac);
    HMAC_Init_ex(&hmac, s3key, strlen(s3key), EVP_sha1(), NULL);

    /* Add Date */
    HMAC_Update(&hmac, req->method, strlen(req->method));
    HMAC_Update(&hmac, "\n", 1);

    /* Add Content-MD5 */
    value = serf_bucket_headers_get(hdrs_bkt, "Content-MD5");
    if (value) {
        HMAC_Update(&hmac, value, strlen(value));
    }
    HMAC_Update(&hmac, "\n", 1);

    /* Add Content-Type */
    value = serf_bucket_headers_get(hdrs_bkt, "Content-Type");
    if (value) {
        HMAC_Update(&hmac, value, strlen(value));
    }
    HMAC_Update(&hmac, "\n", 1);

    /* Add Content-Type */
    value = serf_bucket_headers_get(hdrs_bkt, "Date");
    if (value) {
        HMAC_Update(&hmac, value, strlen(value));
    }
    HMAC_Update(&hmac, "\n", 1);

    /* Add Path */
    HMAC_Update(&hmac, req->path, strlen(req->path));

    HMAC_Final(&hmac, md, &count);
    HMAC_CTX_cleanup(&hmac);

    /* Setup Output */
    enclen = apr_base64_encode_len(count);
    base64 = apr_palloc(pool, enclen);
    apr_base64_encode(base64, md, count);

    signature = apr_psprintf(pool, "AWS %s:%s",
                             req->acceptor_baton->ctx->s3_id, base64);

    memset(md, 0, sizeof(md));

    return signature;
}

